/**************************************************************************
 *
 * Copyright 2014 MaeckySoft Ltd., Bludenz, Austria.
 * All Rights Reserved.
 *
 **************************************************************************/

#include "MFTManager.h"
#include "MTools.h"

//TODO: use std::string instead of (char *)

MFTManager::MFTManager(int iDebug) : M3DBase(iDebug)
{
	if (iDebug >= MDBG_VERBOSE) std::cout << "(" << __FILE__ << ") <DBG_VERBOSE> " << __PRETTY_FUNCTION__ << " called." << std::endl;

    m_FTL_Library=NULL;
    m_FTF_Face=NULL;
    //ctor
}

int MFTManager::initFT()
{
	if (m_iDebug >= MDBG_ALL) this->printMethodInfo(__PRETTY_FUNCTION__);

    int iError=0;
    iError = FT_Init_FreeType (&m_FTL_Library);
    if (iError)
    {
		std::cerr << "(" << __FILE__ << ") <Error> Unable to initialize Freetype." << std::endl;
    }
    return iError;
}

void MFTManager::printMethodInfo(std::string method)
{
	if (m_iDebug == MDBG_ALL) std::cout << "(" << __FILE__ << ") <DBG_ALL> " << method << " called." << std::endl;


}


int MFTManager::loadFont(char *sName)
{
	if (m_iDebug >= MDBG_ALL) this->printMethodInfo(__PRETTY_FUNCTION__);

    int iError=0;
    if (m_FTL_Library==NULL)
    {
		std::cerr << "(" << __FILE__ << ") <Error> Unable to load font: Freetype not initialized." << std::endl;
        return 1;
    }
    iError = FT_New_Face(m_FTL_Library,
                        sName,
                        0,
                        &m_FTF_Face );
    if ( iError == FT_Err_Unknown_File_Format )
    {
		std::cerr << "(" << __FILE__ << ")  <Error> Unable to load font: Font format not supported." << std::endl;
        return iError;
    }
    else if (iError)
    {
		std::cerr << "(" << __FILE__ << ")  <Error> Unable to load font '" << sName << "': File can't be read." << std::endl;
        return iError;
    }
    return iError;
}

int MFTManager::setFontSize(int iPt, int iH_res, int iV_res)
{
	if (m_iDebug >= MDBG_ALL) this->printMethodInfo(__PRETTY_FUNCTION__);

    if (m_FTF_Face==NULL)
    {
		std::cerr << "(" << __FILE__ << ")  <Error> Unable set font size: No font loaded." << std::endl;
        return 1;
    }
    int iError=0;
    iError = FT_Set_Char_Size(
                             m_FTF_Face,    /* handle to face object           */
                             0,       /* char_width in 1/64th of points  */
                             iPt*PT,   /* char_height in 1/64th of points */
                             iH_res,     /* horizontal device resolution    */
                             iV_res );   /* vertical device resolution      */
    if (iError)
    {
		std::cerr << "(" << __FILE__ << ") <Error> Unable set font size." << std::endl;
    }
    return iError;
}

MGlyph *MFTManager::renderCharacter(char cCharacter)
{
	if (m_iDebug >= MDBG_ALL) this->printMethodInfo(__PRETTY_FUNCTION__);

    int iError=0;
    if (m_FTF_Face==NULL)
    {
		std::cerr << "(" << __FILE__ << ") <Error> Unable to render character: No font loaded." << std::endl;
        return NULL;
    }

    FT_UInt  FTUIGlyph_index;
    FTUIGlyph_index = FT_Get_Char_Index( m_FTF_Face, cCharacter);
    iError = FT_Load_Glyph( m_FTF_Face, FTUIGlyph_index, FT_LOAD_DEFAULT );
    if ( iError )
    {
		std::cerr << "(" << __FILE__ << ") <Error> Unable to render character: Unable to load glyph." << std::endl;
        return NULL;
    }

    iError = FT_Render_Glyph( m_FTF_Face->glyph, FT_RENDER_MODE_NORMAL );
    if ( iError ){
		std::cerr << "(" << __FILE__ << ") <Error> Unable to render character: Unable to render glyph." << std::endl;
        return NULL;
    }
    FT_Glyph_Metrics *myMetrics = &m_FTF_Face->glyph->metrics;

    MGlyph *MGReturnGlyph = new MGlyph(m_iDebug);

    unsigned char *sBuffer = new unsigned char [sizeof(unsigned char) * m_FTF_Face->glyph->bitmap.rows * m_FTF_Face->glyph->bitmap.pitch+1];
    memset(sBuffer,0,(sizeof(unsigned char) * m_FTF_Face->glyph->bitmap.rows * m_FTF_Face->glyph->bitmap.pitch+1));

    MGReturnGlyph->setHeight(m_FTF_Face->glyph->bitmap.rows);
    MGReturnGlyph->setWidth(m_FTF_Face->glyph->bitmap.pitch);

    MGReturnGlyph->setCharacter(cCharacter);
    MGReturnGlyph->setWidthPt(myMetrics->width);
    MGReturnGlyph->setHeightPt(myMetrics->height);
    MGReturnGlyph->setBearingX(myMetrics->horiBearingX);
    MGReturnGlyph->setBearingY(myMetrics->horiBearingY);
    MGReturnGlyph->setAdvance(myMetrics->horiAdvance);
    MGReturnGlyph->setPointSize(PT);

    memcpy(sBuffer, m_FTF_Face->glyph->bitmap.buffer, (MGReturnGlyph->getHeight()*MGReturnGlyph->getWidth()));
    MGReturnGlyph->setBuffer(sBuffer);

    return MGReturnGlyph;
}

MFTManager::~MFTManager()
{
	if (m_iDebug >= MDBG_VERBOSE) std::cout << "(" << __FILE__ << ") <DBG_VERBOSE> " << __PRETTY_FUNCTION__ << " called." << std::endl;
    FT_Done_Face    ( m_FTF_Face );
    FT_Done_FreeType( m_FTL_Library );
    //dtor
}
